home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
COMMUNIC
/
0558.ZIP
/
SCANCODE.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-05-01
|
18KB
|
590 lines
page 64,132
COMMENT ;
SCANCODE version 1.2 by Merlin R. Null 4-30-87
A simple table of scancodes in decimal and hex
for use in assembly language programming.
SCANCODE R causes the program to go memory
resident. Without this switch, it is a normal
nonresident program.
; 0 Black 4 Red 8 Gray 12 Light Red
; 1 Blue 5 Magenta 9 Light Blue 13 Light Magenta
; 2 Green 6 Brown 10 Light Green 14 Yellow
; 3 Cyan 7 White 11 Light Cyan 15 High-Intensity White
;Set the following equates to values between 0 and 15 for foreground
;colors and between 0 and 7 for background colors.
;Select a number from 0 to 15 from the above chart.
FrameFgColor EQU 15 ;frame foreground color
FrameBgColor EQU 4 ;frame background color
ChartFgColor EQU 0 ;chart foreground color
ChartBgColor EQU 3 ;chart background color
FrameColor EQU FrameFgColor + (FrameBgColor * 16)
ChartColor EQU ChartFgColor + (ChartBgColor * 16)
;Various Program Equates
MonoSegAddr EQU 0B000h ;address of monochrome buffer
GraphSegAddr EQU 0B800h ;address of graphics buffer
;--------------------------------------------------------------------
Interrupts SEGMENT AT 0h ;interrupt table segment
ORG 9h*4
KeyboardInt DW 2 DUP (0) ;interrupt 9 vector
Interrupts ENDS
Code SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:Code
ORG 100h ;COM format
Begin: JMP Initialize ;goto initialization routine
DisplayTable DB 2Dh,29h ;display re-enable values for
; modes 2 and 3
Video DW 0B800h,0B900h ;starting addresses of video
DW 0BA00h,0BB00h ; memory for CGA pages 0 - 3
DW 0B000h ;video segment address for
;monochrome
ScanData DB '╔════════════╤════════════╤════════════╤'
DB '═════════════╗■'
DB '║ KEY DEC HEX│ KEY DEC HEX│ KEY DEC HEX│'
DB ' KEY DEC HEX║■'
DB '║ Aa 30 1E │ Vv 47 2F │ ,< 51 33 │'
DB ' Rtrn 28 1C ║■'
DB '║ Bb 48 30 │ Ww 17 11 │ .> 52 34 │'
DB ' Alt 56 38 ║■'
DB '║ Cc 46 2E │ Xx 45 2D │ /? 53 35 │'
DB ' Ctrl 29 1D ║■'
DB '║ Dd 32 20 │ Yy 21 15 │ \| 43 2B │'
DB ' CpLk 58 3A ║■'
DB '║ Ee 18 12 │ Zz 44 2C │ `~ 41 29 │'
DB ' LtSh 42 2A ║■'
DB '║ Ff 33 21 │ 1! 2 2 │ SP 57 39 │'
DB ' RtSh 54 36 ║■'
DB '║ Gg 34 22 │ 2@ 3 3 │ BS 14 E │'
DB ' *PrS 55 37 ║■'
DB '║ Hh 35 23 │ 3# 4 4 │ Tab 15 F │'
DB ' Ins 82 52 ║■'
DB '║ Ii 23 17 │ 4$ 5 5 │ Esc 1 1 │'
DB ' Del 83 53 ║■'
DB '║ Jj 36 24 │ 5% 6 6 │ - 74 4A │'
DB ' NmLk 69 45 ║■'
DB '║ Kk 37 25 │ 6^ 7 7 │ + 78 4E │'
DB ' ScLk 70 46 ║■'
DB '║ Ll 38 26 │ 7& 8 8 │ F1 59 3B │'
DB ' Lt 75 4B ║■'
DB '║ Mm 50 32 │ 8* 9 9 │ F2 60 3C │'
DB ' Rt 77 4D ║■'
DB '║ Nn 49 31 │ 9( 10 A │ F3 61 3D │'
DB ' Up 72 48 ║■'
DB '║ Oo 24 18 │ 0) 11 B │ F4 62 3E │'
DB ' Dn 80 50 ║■'
DB '║ Pp 25 19 │ -_ 12 C │ F5 63 3F │'
DB ' PgUp 73 49 ║■'
DB '║ Qq 16 10 │ =+ 13 D │ F6 64 40 │'
DB ' PgDn 81 51 ║■'
DB '║ Rr 19 13 │ [{ 26 1A │ F7 65 41 │'
DB ' Home 71 47 ║■'
DB '║ Ss 31 1F │ ]} 27 1B │ F8 66 42 │'
DB ' End 79 4F ║■'
DB '║ Tt 20 14 │ ;: 39 27 │ F9 67 43 │'
DB ' Pad5 76 4C ║■'
DB '║ Uu 22 16 │ ',39,'" 40 28 │ F10 68 44 │'
DB ' SCAN CODES ║■'
DB '╚════════════╧════════════╧════════════╧'
DB '═════════════╝',0
FrameAtr DB 70
ChartAtr DB 7
VideoMode DW 0 ;video mode number
ColumnCount DW 0 ;width of window in columns
CursorPos DW 0 ;cursor position
SetupStatus DB 0 ;indicates if window
; is already active
PageNo DW 0 ;current displayed page
OldKbInt LABEL DWORD
OldKeyboardInt DW 2 DUP (0) ;storage for old keyboard
ResFlag DB 0 ;memory resident flag
MonoFlag DB 0 ;monochrome only flag
;---------------------------------------------------------------------------
;Execution comes here, to the main body of the program, when an interrupt 9
;is generated from the keyboard. Registers are saved, then the keypress is
;checked and compared to the key combination that activates the menu window.
;This routine is only called if the SCANCODE is memory resident.
Main: STI ;enable software interrupts
PUSH AX ;save all registers
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
PUSH AX ;save AX for call to old
; routine
IN AL,0A0h ;re-enable NMI on PCjr
POP AX ;restore AX
PUSHF ;simulate interrupt call to
; old keyboard routine
CALL OldKbInt ;call old routine
MOV AH,2 ;check status of the shift
; keys
INT 16h
AND AL,00000111b ;Ctrl, Rt-Shift and Lt-Shift
CMP AL,00000111b ;depressed?
JE DoProgram ;if so, then skip exit routine
;Exit routine is the common point of exit for all routines in the program.
Exit: POP ES
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
IRET
;Execution comes here when the proper key combination, Ctrl/Rt-Shift, is
;pressed. First task is to check whether or not the window is already open.
DoProgram: PUSH CS ;set ES and DS to the code
; segment
POP DS
PUSH CS
POP ES
CMP SetupStatus,0 ;is the window already open?
JNE Exit ;yes, then ignore request
;----------------------------------------------------------------------------
;Check current video mode. If it's mode 2, 3, or 7, then set the window
;status flag, store the mode number and page number, save the cursor
;position. If any other display mode is active instead, ignore the
;request and exit.
CALL GetMode ;get page and mode numbers
CMP AL,2 ;is crt now in an acceptable
; mode?
JE Prog0 ;yes, then continue
CMP AL,3
JE Prog0
CMP AL,7
JE Prog0
JMP Exit ;no, then ignore request
Prog0: MOV SetupStatus,1 ;set status flag to indicate
; that window is active
MOV BL,BH ;save page number for color
; displays
XOR BH,BH
MOV PageNo,BX
;Start of code common to both memory resident and nonresident modes
DoNonResProg: MOV AH,3 ;get cursor position
INT 10h
MOV CursorPos,DX ;save it
CALL GetMode
CMP AL,7 ;is it monochrome?
JE Mono
CMP MonoFlag,1 ;Monochrome override set?
JE Mono
MOV FrameAtr,FrameColor ;set screen colors
MOV ChartAtr,ChartColor
JMP SHORT Prog1
Mono: MOV FrameAtr,70h ;set monochrome attributes
MOV ChartAtr,7 ;normal video
CMP ResFlag,1 ;if non-res, bypass screen
JNE DisplayChart ; save
;Preparatory routines are completed. Now open the window by first saving the
;contents of video memory beneath the window and then writing the window text
;directly to memory.
Prog1: MOV BX,PageNo ;use BX as index into video
; segment address table
CALL GetMode ;get crt mode
CMP AL,7
JNE Prog2
MOV BX,4 ;manually adjust index for
; monochrome adapter
Prog2: SHL BX,1 ;multiply BX by two since
; table is made up of words
MOV AX,Video[BX] ;read segment from table
MOV DS,AX ;DS set to video memory
CALL VideoDisable ;turn display off
LEA DI,WindowBuffer ;set DI to buffer area to save
; screen contents
MOV CX,3618h ;54 columns 24 rows
; in the window
MOV DX,000Dh ;row 0 col 13
; upper left corner of window
CALL Video2Mem ;then transfer screen contents
; to buffer
DisplayChart: PUSH DS ;set ES to video memory
POP ES
PUSH CS ;reset DS to code segment
POP DS
LEA SI,ScanData ;print scan code chart
MOV DX,000Dh ;row 0 col 13
CALL InsertString
MOV DX,1900h ;move cursor off screen
CALL Locate
GetKey: XOR AH,AH ;get a keypress
INT 16h ;BIOS keyboard input
CMP AH,1 ;esc?
JNE GetKey
CMP ResFlag,1
JE EscapeOut
MOV DX,1700h
CALL Locate
INT 20h
;Execution comes here when the Esc key is pressed. The window is refilled
;with its original contents, the cursor is restored, and control is handed
;back to the application program.
EscapeOut: CALL VideoDisable ;turn off the display
LEA SI,WindowBuffer ;point to the buffer area
;define the window
MOV CX,3618h ;54 columns 24 lines
MOV DX,000Dh ;upper left corner
;row 0 col 13
CALL Mem2Video ;and write the buffer contents
; to the display
CALL VideoEnable ;turn display back on
MOV DX,CursorPos ;restore cursor position
CALL Locate
CMP ResFlag,0 ;is the program resident?
JNE ResExit
INT 20h ;if not, normal exit
ResExit: MOV SetupStatus,0 ;reset window status
JMP Exit ;and exit
;-----------------------------------------------------------------------------
;Insert String Directly in the Video Buffer
; SI string address DX row, column
InsertString: PUSH ES
CALL VideoDisable
CALL CalcVidOffset ;calc video offset
MOV DI,AX ;offset was returned in AX
CALL SetVidAddr ;set to monochrome or graphics
MOV ES,AX ;video buffer address into ES
MOV AX,80 ;max chars per line
InsertLoop: MOV DH,ChartAtr ;set chart color
MOV DL,BYTE PTR[SI]
CMP DL,0
JE InsertStrExit ;exit if end of string
CMP DL,0FEh ;end of line marker?
JNE InsertLoop2
SHL AX,1 ;skip remaining positions on
ADD DI,AX ; this line
MOV AX,80 ;and reset char count
JMP SHORT NextByte
InsertLoop2: CMP DL,128
JB InsertWord
MOV DH,FrameAtr
InsertWord: MOV ES:WORD PTR[DI],DX ;move char and attr to crt buf
ADD DI,2 ;point to next crt buf loc
SUB AX,1 ;dec available chars this line
NextByte: ADD SI,1 ;point to next string byte
JMP InsertLoop ;move another word
InsertStrExit: CALL VideoEnable ;video back on if CGA
POP ES
RET
;--------------------------------------------------------------------
;Direct Cursor Addressing
Locate: PUSH BX
MOV AH,2 ;request move cursor
MOV BX,PageNo ;get active page no.
MOV BH,BL
INT 10h
POP BX
RET
;---------------------------------------------------------------------------
;Video2Mem routine transfers the contents of a portion of video memory
;to a memory buffer for storage.
;Entry: DS - video segment
; ES:DI - memory buffer
; DH,DL - row and column of upper left corner of window
; CH - width of window in columns
; CL - number of lines in window
Video2Mem: MOV AL,CH ;store number of columns
XOR AH,AH
MOV ColumnCount,AX
XOR CH,CH ;CX = number of lines
PUSH DI ;save DI
CALL CalcVidOffset ;get cell address of first
; character
MOV SI,DI ;put it in SI
POP DI ;restore DI
Video2Mem1: PUSH SI ;save SI for next line
PUSH CX ;save line count
MOV CX,ColumnCount ;set CX for call to WriteLn
CALL WriteLn ;transfer one line
POP CX ;restore saved registers
POP SI
ADD SI,160 ;set next line start address
LOOP Video2Mem1 ;loop until all lines are done
RET
;---------------------------------------------------------------------------
;Mem2Video writes a selected area of memory to the video display.
;Entry: DS:SI - memory buffer
; ES - video segment
; DH,DL - row and column of upper left corner of window
; CH - width of window in columns
; CL - number of lines in window
Mem2Video: MOV AL,CH ;save number of columns
XOR AH,AH
MOV ColumnCount,AX
XOR CH,CH ;CX = number of lines
CALL CalcVidOffset ;get offset into video memory
Mem2video1: PUSH DI ;save video starting address
PUSH CX ;save line count
MOV CX,ColumnCount ;set CX for call to WriteLn
CALL WriteLn ;transfer one line
POP CX ;restore registers
POP DI
ADD DI,160 ;set DI for next display line
LOOP Mem2video1 ;loop until done
RET
;---------------------------------------------------------------------------
;WriteLn subroutine copies a string of words from one memory location to
;another. The CGA status port is not checked for vertical retrace status
;before transfer.
;Entry: DS:SI - source
; ES:DI - destination
; CX - number of words
WriteLn: CLD ;clear for string instructions
Write1: MOVSW ;move one word
LOOP Write1 ;loop until done
RET
;--------------------------------------------------------------------
;Get Video Mode.
;Returns CRT mode in AL and the number of character columns on the
;screen in AH.
GetMode: MOV AH,15 ;get page and mode numbers
;AL=mode, BH=page
INT 10h ;BIOS video request
XOR AH,AH
MOV VideoMode,AX
RET
;--------------------------------------------------------------------
;Set Video Address
SetVidAddr: CALL GetMode
CMP AL,7 ;is it monochrome
JNE ItsGraphics
MOV AX,MonoSegAddr ;monochrome buffer seg addr
RET
ItsGraphics: MOV AX,GraphSegAddr ;graphics buffer seg address
RET
;--------------------------------------------------------------------
;Calculate Video Address
;Entry: DH,DL - row and column of cell (0-24,0-79)
;Exit: DI - offset address
CalcVidOffset: MOV AX,160 ;number of bytes in row
MUL DH ;row * 160
SHL DL,1 ;column * 2
XOR DH,DH ;byte to word
ADD AX,DX ;(row *160)+(column*2)
MOV DI,AX ;set offset in DI
RET
;---------------------------------------------------------------------------
;VideoEnable and VideoDisable routines manipulate bit 3 of port 3D8h,
;the CGA Mode Control Register, to temporarily turn the display on or off.
;These routines write directly to hardware, and have no effect on other
;video adapters.
VideoDisable: PUSH DX
CMP VideoMode,7 ;skip disable if in mode 7
JE Disable2
MOV DX,3DAh ;read CGA status port
Disable1: IN AL,DX ;wait for vertical retrace to
;occur
TEST AL,8 ;is bit 3 set?
JE Disable1 ;no, wait until it is
MOV DX,3D8h ;now disable the display
MOV AL,25h ;by clearing bit 3 of the Mode
; Control Register
OUT DX,AL
Disable2: POP DX
RET
; - - - - - - - - -
VideoEnable: CMP VideoMode,7 ;skip enable if in mode 7
JE Enable2
MOV DX,3D8h ;CGA Mode Control Register
MOV BX,VideoMode ;get re-enable display value
SUB BX,2
MOV AL,DisplayTable[BX]
OUT DX,AL ;and send it to the port
Enable2: RET
;----------------------------------------------------------------------------
;This area is used to store the contents of the screen that underlies the
;window when the window is called up. It overwrites the initialization
;code, since it is not needed after the program is started.
WindowBuffer EQU $
BuffEnd EQU $+2592
;---------------------------------------------------------------------------
;Print hard copy of scancode chart
PrintChart: LEA SI,ScanData
JMP SHORT CRLFnMargin
PrintLoop: LODSB
CMP AL,0
JE PrintDone
CMP AL,0FEh
JE CRLFnMargin
MOV DL,AL
MOV AH,5
INT 21h
JMP PrintLoop
;Print CR & LF followed by margin for next line
CRLFnMargin: PUSH SI
LEA SI,CRLFnMarginDat
CRLFnLoop: LODSB
CMP AL,0
JZ CRLFnMExit
MOV DL,AL
MOV AH,5
INT 21h
JMP CRLFnLoop
CRLFnMExit: POP SI
JMP PrintLoop
PrintDone: MOV DL,0Ch ;send final formfeed
MOV AL,5
INT 21h
INT 20h ;all done
;---------------------------------------------------------------------------
;Data used only by printer or help display
CRLFnMarginDat DB 0Dh,0Ah,13 DUP (' '),0
HelpScreenDat: DB 'Useage:■■'
DB 'SCANCODE [?HMPR]■■'
DB '? or H This help screen■'
DB 'M Mono (for composite)■'
DB 'P Printer only (IBM Character set required)■'
DB 'R Go memory Resident■',0
;---------------------------------------------------------------------------
ClearScreen: MOV AX,0600h ;scroll active page
MOV BH,7 ;normal screen attribute
XOR CX,CX ;upper left
MOV DX,184Fh ;lower right
INT 10h ;call BIOS
RET
;---------------------------------------------------------------------------
;Print instructions if flags ? or H are found
HelpScreen: CALL GetMode ;store mode
CALL ClearScreen
MOV DX,0800h ;row 8 col 0
LEA SI,HelpScreenDat
CALL InsertString
MOV DX,1700H ;row 23 col 0
CALL Locate
INT 20h
;---------------------------------------------------------------------------
;Initialization routine checks the command line for switches. If resident
;switch is set, saves and replaces the old keyboard interrupt vector.
Initialize: ASSUME DS:Code,ES:Code
MOV DX,80h ;point to command line tail
MOV SI,DX
MOV DL,[SI]
CMP DL,2 ;no tail?
JB NonRes ;if so, run nonresident mode
INC SI ;skip separator
ComTailLoop: INC SI
MOV DL,[SI]
CMP DL,'?'
JE HelpScreen
AND DL,5Fh ;mask to upper case
CMP DL,'H'
JE HelpScreen
CMP DL,'P' ;print flag?
JNE CheckMono
JMP PrintChart ;print hard copy
CheckMono: CMP DL,'M' ;switch for monochrome only?
JNE CheckResSwitch
MOV MonoFlag,1 ;if so, set flag
CheckResSwitch: CMP DL,'R' ;switch for TSR?
JNE NextChar
MOV ResFlag,1 ;if so, set flag
NextChar: CMP DL,0Dh ;return?
JNE ComTailLoop ;if not, check next char
CMP ResFlag,1 ;resident flag set?
JE GoResident
NonRes: CALL ClearScreen
JMP DoNonResProg
;Save the old keyboard interrupt vector and replace it with the new one.
GoResident: MOV AX,Interrupts ;set DS to the interrupt
; vector area
MOV DS,AX
ASSUME DS:Interrupts
MOV AX,KeyboardInt ;save old vector
MOV OldKeyboardInt,AX
MOV AX,KeyboardInt[2]
MOV OldKeyboardInt[2],AX
CLI ;disable all interrupts but
; NMI
MOV KeyboardInt,OFFSET Main ;and install new vector
MOV KeyboardInt[2],CS
STI ;re-enable interrupts
MOV DX,OFFSET BuffEnd+1 ;point DX to end of resident
; section
INT 27h ;terminate-but-stay-resident
Code ENDS
END Begin